package archer.framework.utils;

import archer.framework.core.exception.BaseException;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;

/**
 * AES 128 算法
 *
 * @author christ
 * @date 2015/9/29
 */
public class AESUtils {

    private static Logger logger = LoggerFactory.getLogger(AESUtils.class);

    private static String algorithmStr = "AES";

    private static KeyGenerator keyGen;

    private static Cipher cipher;

    private static boolean init = false;

    /**
     * 初始化
     */
    static private void init() {

        //初始化keyGen
        try {
            keyGen = KeyGenerator.getInstance("AES");
            keyGen.init(128);
            cipher = Cipher.getInstance(algorithmStr);
        } catch (Exception e) {
            logger.error("AES加密解密异常", e);
            throw new BaseException("AES加密解密异常", e);
        }
        init = true;
    }

    public static byte[] genKey() {

        if (!init) {
            init();
        }
        return keyGen.generateKey().getEncoded();
    }

    /**
     * 生成16进制表示的SecretKeySpec
     *
     * @return
     */
    public static String genHexKey() {

        return Hex.encodeHexString(genKey());
    }

    /**
     * 加密
     *
     * @param content
     * @param keyBytes
     * @return
     */
    public static byte[] encrypt(byte[] content, byte[] keyBytes) {

        if (ValidateUtils.isEmpty(content) || ValidateUtils.isEmpty(keyBytes)) {
            return null;
        }

        if (!init) {//为初始化
            init();
        }

        Key key = new SecretKeySpec(keyBytes, "AES");

        try {
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return cipher.doFinal(content);
        } catch (Exception e) {
            logger.error("AES加密异常", e);
            throw new BaseException("AES加密异常", e);
        }
    }

    /**
     * 解密
     *
     * @param content
     * @param keyBytes
     * @return
     */
    public static byte[] decrypt(byte[] content, byte[] keyBytes) {

        if (ValidateUtils.isEmpty(content) || ValidateUtils.isEmpty(keyBytes)) {
            return null;
        }

        if (!init) {
            init();
        }

        Key key = new SecretKeySpec(keyBytes, "AES");

        try {
            cipher.init(Cipher.DECRYPT_MODE, key);
            return cipher.doFinal(content);
        } catch (Exception e) {
            logger.error("AES解密异常", e);
            throw new BaseException("AES解密异常", e);
        }
    }

}
